<?php

namespace app\models;

use app\components\helpers\ArrayHelper;
use app\components\helpers\MappingHelper;
use Yii;

use yii\behaviors\TimestampBehavior;
use yii\db\Query;
use yii\db\Exception;
use yii\data\Pagination;
use yii\db\ActiveQuery;
use yii\filters\RateLimitInterface;
use yii\helpers\Json;
use yii\web\IdentityInterface;
use yii\data\ArrayDataProvider;

/**
 * 用户模型
 * @property int $id
 * @property string $number
 * @property string $username
 * @property string $password
 * @property string $access_token
 * @property int $status
 * @property int $allowance
 * @property int $allowance_updated_at
 * @property int $login_count
 * @property int $login_ip
 * @property int $login_at
 * @property int $created_at
 * @property int $updated_at
 * @property int $is_deleted
 * @property int $deleted_at
 */
class User extends ActiveRecord implements IdentityInterface, RateLimitInterface
{
    public function behaviors()
    {
        return [['class' => TimestampBehavior::class]];
    }

    public function getRateLimit($request, $action)
    {
        return [30, 60];
    }

    public function loadAllowance($request, $action)
    {
        return [$this->allowance, $this->allowance_updated_at];
    }

    public function saveAllowance($request, $action, $allowance, $timestamp)
    {
        $this->allowance = $allowance;
        $this->allowance_updated_at = $timestamp;
        $this->save();
    }

    /**
     * @throws \yii\base\Exception
     */
    public function setPassword()
    {
        $this->password = app()->security->generatePasswordHash($this->password);
    }

    /**
     * @param bool $insert
     * @return bool
     * @throws \yii\base\Exception
     */
    public function beforeSave($insert)
    {
        if (parent::beforeSave($insert)) {
            if ($insert) {
                $this->setPassword();
            }
            return true;
        }
        return false;
    }

    public function rules()
    {
        return [
            [
                [
                    'number',
                    'username',
                    'password',
                    'access_token',
                    'status',
                    'allowance',
                    'allowance_updated_at',
                    'login_count',
                    'login_at',
                    'login_ip',
                    'is_deleted',
                    'deleted_at'
                ],
                'safe'
            ]
        ];
    }

    public static function tableName()
    {
        return '{{%user}}';
    }

    public static function find()
    {
        return new ActiveQuery(get_called_class());
    }

    public static function findIdentity($id)
    {
        return static::findOne($id);
    }

    public static function findIdentityByAccessToken($token, $type = null)
    {
        return static::findOne(['access_token' => $token]);
    }

    /**
     * @throws \yii\base\Exception
     */
    public function generateAccessToken()
    {
        $this->access_token = Yii::$app->security->generateRandomString();
    }

    public static function findByUsername($username)
    {
        return static::findOne(['username' => $username]);
    }

    public function getDept()
    {
        return $this->hasOne(Department::class, ['id' => 'dept_id']);
    }

    public function getPosition()
    {
        return $this->hasOne(Position::class, ['id' => 'position_id']);
    }

    public function getId()
    {
        return $this->id;
    }

    public function getAuthKey()
    {
        return $this->authKey;
    }

    public function validateAuthKey($authKey)
    {
        return $this->authKey === $authKey;
    }

    public function validatePassword($password)
    {
        return Yii::$app->security->validatePassword($password, $this->password_hash);
    }

    /**
     * 获取岗位下的用户
     * @param $positionId
     * @return array
     */
    public function getForPosition($positionId)
    {
        $query = self::find()->alias('u')->where(['position_id' => $positionId]);
        $query->select([
            'u.username',
            'u.email',
            'u.dept_id'
        ]);
        $query->joinWith([
            //'role' => function ($q) {
            // $q->select(['name']);
            //},
            'dept' => function ($q) {
                $q->select(['name', 'id']);
            }
        ]);

        $pagination = new Pagination([
            'defaultPageSize' => 50,
            'totalCount' => $query->count()
        ]);

        $data = $query->offset($pagination->getOffset())
            ->orderBy('u.id DESC')
            ->limit($pagination->getLimit())->all();

        $dataProvider = new ArrayDataProvider([
            'models' => $data,
            'Pagination' => $pagination,
        ]);

        $user = [];
        $models = $dataProvider->getModels();

        foreach ($models as $arr) {
            $user[] = [
                'username' => $arr['username'],
                'email' => $arr['email'],
                'dept' => $arr->dept->name,
            ];
        }

        $pageSize = $pagination->getPageSize();
        $totalPage = $pagination->getPageCount();
        $totalCount = $pagination->totalCount;

        return [
            'user' => $user,
            //'totalCount' => (int)$totalCount,
            //'pageSize' => $pageSize,
            //'totalPage' => $totalPage,
        ];
    }

    /**
     * 获取某岗位下的用户列表
     * @param $positionId
     * @return array|\yii\db\ActiveRecord[]
     */
    public static function getListByPositionId($positionId)
    {
        $query = self::find()->alias('u');
        $query->leftJoin(Department::tableName() . ' d', 'u.dept_id = d.id');
        $query->select(['u.username', 'u.email', 'd.name AS dept']);
        $query->where(['u.position_id' => $positionId]);
        return $query->all();
    }

    /**
     * 查询 包含某 权限项 的用户列表
     * @param $param
     * @return array
     */
    public static function getListByItemId($param)
    {
        $query = new Query;
        $query->select([
            'u.username',
            'FROM_UNIXTIME(u.created_at, "%Y-%m-%d %H:%i:%S") AS createdAt',
            'i.name AS item',
            'u.id AS userId'
        ]);
        $query->from('{{%user_item}} ui');
        $query->leftJoin('{{%user}} u', 'u.id=ui.user_id');
        $query->leftJoin('{{%item}} i', 'i.id=ui.item_id');
        $query->andFilterWhere(['like', 'u.username', $param['name']]);
        $query->andFilterWhere(['ui.item_id' => $param['id']]);

        $pagination = new Pagination([
            'defaultPageSize' => 10,
            'totalCount' => $query->count()
        ]);

        $pagination->setPage($param['page'] - 1);
        $pagination->setPageSize($param['pageSize']);
        $data = $query->offset($pagination->getOffset())->orderBy('u.id DESC')
            ->limit($pagination->getLimit())->all();

        $dataProvider = new ArrayDataProvider([
            'models' => $data,
            'Pagination' => $pagination,
        ]);

        $user = $dataProvider->getModels();
        $pageSize = $pagination->getPageSize();
        $totalPage = $pagination->getPageCount();
        $totalCount = $pagination->totalCount;

        return [
            'user' => $user,
            'totalCount' => (int)$totalCount,
            'pageSize' => $pageSize,
            'totalPage' => $totalPage,
        ];
    }

    /**
     * 根据权限项移除下属用户
     * @param $param
     * @throws Exception
     */
    public function removeByItem($param)
    {
        Yii::$app->db->createCommand()
            ->delete('{{%user_item}}', ['and', ['item_id' => $param['id']], ['in', 'user_id', $param['userId']]])
            ->execute();
    }

    private function _makeUpItem($item, $auth, $data)
    {
        if (empty($item)) {
            return [];
        }
        $userItem = [];
        foreach ($item as $i) {
            $userItem[] = [
                'type' => isset($auth[$i]) ? $auth[$i] : 0,
                'user_id' => $this->id,
                'item_id' => $i,
                'data' => isset($data[$i]) ? Json::encode($data[$i]) : ''
            ];
        }
        return $userItem;
    }

    /**
     * 写入个人权限
     * @param $item
     * @param $auth
     * @param $data
     * @throws Exception
     */
    public function addItem($item, $auth, $data)
    {
        $item = $this->_makeUpItem($item, $auth, $data);
        $item ? Yii::$app->db->createCommand()
            ->batchInsert('{{%user_item}}', ['type', 'user_id', 'item_id', 'data'], $item)
            ->execute() : '';
    }

    /**
     * 移除个人权限
     * @throws Exception
     */
    public function removeItem()
    {
        Yii::$app->db->createCommand()
            ->delete('{{%user_item}}', ['user_id' => $this->id])
            ->execute();
    }

    public function getItem($id)
    {
        // 所有权限项
        $itemArr = Item::find()->select([
            'id',
            'name',
            'parent_id AS pid',
            'data_auth AS auth',
            '(0) AS type',
            '(0) AS checked'
        ])->asArray()->all();

        $newArr = array_combine(array_column($itemArr, 'id'), array_values($itemArr));

        // 已经赋予的权限项
        $uItems = (new Query)->select(['item_id AS id', 'type'])
            ->from('{{%user_item}}')
            ->where(['user_id' => $id])->all();
        foreach ($uItems as $pi) {
            if (isset($newArr[$pi['id']])) {
                $newArr[$pi['id']]['type'] = $pi['type'];
                $newArr[$pi['id']]['checked'] = 1;
            }
        }

        $arr['typeList'] = MappingHelper::dataAuthList();
        $arr['item'] = ArrayHelper::treeFormat($newArr);
        return $arr;
    }

    public function getRole($id)
    {
        $query = new Query;
        $query->select(['role_id']);
        $query->from('{{%user_role}}');
        $query->where(['user_id' => $id]);
        return $query->all();
    }

    /**
     * 创建 用户
     * @param $user
     * @param $profile
     * @param $role
     */
    public static function performCreate($user, $profile, $role)
    {
        $db = app()->db;
        $trans = $db->beginTransaction();
        try {

            // 用户
            $user['access_token'] = app()->security->generateRandomString();
            $user['status'] = MappingHelper::STATUS_ACTIVE;
            $user['allowance'] = 0;
            $user['allowance_updated_at'] = 0;
            $user['login_count'] = 0;
            $user['login_ip'] = '';
            $user['login_at'] = 0;
            $user['is_deleted'] = 0;
            $user['deleted_at'] = 0;
            $model = new self();
            $model->setAttributes($user);
            $model->save(false);

            // 附表信息
            $profile['uid'] = $model->id;
            $profile['updated_at'] = $_SERVER['REQUEST_TIME'];
            $p = new UserProfile;
            $p->setAttributes($profile);
            $p->group_path = $p->group->path;
            $p->dept_path = $p->dept->path;
            $p->save(false);

            // 角色
            if (!empty($role)) {
                $userRole = [];
                foreach ($role as $ro) {
                    $ro ? $userRole[] = ['user_id' => $model->id, 'role_id' => $ro] : '';
                }
                if (!empty($userRole)) {
                    $cmd = $db->createCommand();
                    $cmd->batchInsert(UserRole::tableName(), ['user_id', 'role_id'], $userRole);
                    $cmd->execute();
                }
            }

            $trans->commit();
        } catch (\Exception $e) {
            $trans->rollBack();
            dump($e->getMessage());
        }
    }
}
